#pragma once
#include <string.h>
#include <iostream>
#include <memory>
#include <cstdlib>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include "Log.hpp"
#include "Commn.hpp"
#include <sys/wait.h>
#include <pthread.h>
#include "ThreadPool.hpp"
#include <functional>

#define BACKLOG 1
const uint16_t gport = 8888;
using namespace LogModule;
using namespace MyThreadPool;
using task_t = std::function<void(void)>;

sockaddr_in peer;

class TcpServer
{
struct PthreadData
{
    TcpServer* self;
    int fd;
};
public:
    TcpServer(uint16_t port = gport)
        : _port(port),
          _isrunning(false)
    {
    }
    void InitServer()
    {
        _listensockfd = ::socket(AF_INET, SOCK_STREAM, 0); //进行监听
        if (_listensockfd < 0)
        {
            LOG(LogLevel::FATAL) << "create listensockfd error";
            Die(SOCKET_ERROR);
        }
        LOG(LogLevel::INFO) << "create listensockfd success, listensockfd is: " << _listensockfd;
	int opt = 1;
	setsockopt(_listensockfd,SOL_SOCKET,SO_REUSEADDR | SO_REUSEPORT,&opt,sizeof(opt));
        sockaddr_in local;

        local.sin_addr.s_addr = INADDR_ANY;
        local.sin_family = AF_INET;
        local.sin_port = ::htons(_port);
        socklen_t len = sizeof(local);
        int n = ::bind(_listensockfd, CONV(&local), len);
        if (n < 0)
        {
            LOG(LogLevel::FATAL) << "bind error";
	    Die(BIND_ERROR);
        }
        LOG(LogLevel::INFO) << "bind success";

        // 连接
        int n1 = ::listen(_listensockfd, BACKLOG); //招呼客人进店
        if (n1 < 0)
        {
            LOG(LogLevel::FATAL) << "listen listensocketfd :" << _listensockfd << " error";
            Die(LISTEN_ERROR);
        }
        LOG(LogLevel::INFO) << "listen listensocketfd :" << _listensockfd << " success";

    }
    void HandlerRequest(int socketfd)
    {
        LOG(LogLevel::INFO) << "HandlerRequest socketfs is: " << socketfd;
        char inbuffer[4096];
        while (true)
        {
            int n = ::recv(socketfd, inbuffer, sizeof(inbuffer)-1,0);
            if (n > 0)
            {
                inbuffer[n] = 0;
                LOG(LogLevel::INFO) << inbuffer;
                std::string clie = "server_echo # ";
                clie += inbuffer;
                int n1 = ::send(socketfd, clie.c_str(), clie.size(),0);
            }
            else if(n == 0)
            {
                std::cout << "client quit: " << socketfd << std::endl;
                break;
            }   
            else return;
        }
	sleep(2);//让服务器休眠2秒
        ::close(socketfd); //关闭文件描述符
    }
    static void* PthreadEnter(void*args)
    {
        pthread_detach(pthread_self()); //把自己与主线程分离，主线程不需要管我了。
        PthreadData* data = (PthreadData*)args;
        std::cout << " socketfd: " << data->fd << std::endl;
        data->self->HandlerRequest(data->fd);
        return nullptr;
    }
    void Start()
    {
        _isrunning = true;
        while (_isrunning)
        {
            memset(&peer, 0, sizeof(peer));
            socklen_t len = sizeof(peer);
	    int socketfd = accept(_listensockfd,CONV(&peer),&len);
            if (socketfd < 0)
            {
                LOG(LogLevel::WARNING) << "accept fd error, repeat";
                continue;
            }
            //version-0
            // 连接成功
            LOG(LogLevel::INFO) << "accept socketfd success socketfd is: " << socketfd;

            task_t t = [this,socketfd](){
                this->HandlerRequest(socketfd);
            };
            threadpool<task_t>::Getinstance()->Equeue(t);

        }
    }
    void Stop()
    {
        _isrunning = false;
    }
    ~TcpServer()
    {
    }

private:
    int _listensockfd;
    uint16_t _port;
    bool _isrunning;
};

